#include <iostream>

// 类模板：类的成员变量类型变成了参数
// template <class T> 没有区别
template <typename T>
class DynamicArray
{
public:
    DynamicArray()
    {
        capacity = 15;
        size = 0;
        array = new T[capacity];
    }

    ~DynamicArray();

    void Insert(const T &element)
    {
        if (size == capacity)
        {
            capacity *= 2;
            T *newP = new T[capacity];
            for (int i = 0; i < size; i++)
            {
                newP[i] = array[i];
            }
            delete array;
            array = newP;
        }
        array[size++] = element;
    }

    // void show()
    // {
    //     for (int i = 0; i < size; i++)
    //     {
    //         std::cout << array[i] << " ";
    //     }
    //     std::cout << std::endl;
    // }

    // 类模板的友元函数在类中声明需要声明模板
    // 友元声明的模板名不能和类模板的模板名相同
    template <typename T1>
    friend std::ostream &operator<<(std::ostream &os, const DynamicArray<T1> &a);

    // = 的赋值运算符重载（返回值还是自己）
    DynamicArray<T> &operator=(const DynamicArray<T> &a)
    {
        std::cout << "赋值运算符重载！\n";
        delete[] array;
        capacity = a.capacity;
        size = a.size;
        array = new T[capacity];
        for (int i = 0; i < size; i++)
        {
            array[i] = a.array[i];
        }
        return *this;
    }

private:
    T *array;
    int capacity;
    int size;
};

// 重载输出运算符
// 这不是类的函数在类外定义，它就是一个全局函数，要声明为友元
template <typename T>
std::ostream &operator<<(std::ostream &os, const DynamicArray<T> &a)
{
    for (int i = 0; i < a.size; i++)
    {
        os << a.array[i] << " ";
    }
    os << std::endl;
    return os;
}

// 如果把所有函数写在类里面那类就会变得很长
// 现在把类模板函数定义在类的外部
template <typename T>
DynamicArray<T>::~DynamicArray() // 单独的DynamicArray不是类模板的名字，必须要加上类型
{
    std::cout << "析构函数！\n";
    delete[] array;
}

int main()
{
#if 0
    // 类模板单独定义时只能显式调用（DynamicArray不是类的名字，只表示类模板，要带上具体类型才真正表示一个类）
    DynamicArray<int> a;
    for (int i = 0; i < 20; i++)
    {
        a.Insert(i + 1);
    }
    a.show();
#endif

#if 1
    // 类模板可以嵌套
    // 一维数组变二维数组
    DynamicArray<DynamicArray<int>> a;

    DynamicArray<int> a1;
    for (int i = 0; i < 20; i++)
    {
        a1.Insert(i + 1);
    }

    DynamicArray<int> a2;
    for (int i = 0; i < 20; i++)
    {
        a2.Insert(i + 1);
    }

    a.Insert(a1);
    a.Insert(a2);
    // a.show();
    std::cout << a;
    // 两次运算符重载：将数组拷给另外一个数组的时候发生的，两个数组就拷两次
    // 18次析构：a这个数组里创建对象时构建了15个一维数组，加上a1,a2和a自己
#endif
    return 0;
}